'''
coding:utf-8
:writingtime: 2022-6-26
:author: wanjun
:reference: 区间值广义正交模糊幂算子及群决策方法
:doi: 数学的实践与认识. 2021,51(16)
:examiner:
'''

import os
from Utilities.AutoGetOperator.selectPackage import get_func


Operator_IVQ_ROFS=get_func(r'Operators/OperationOperators/OperatorIVQROF.py','Operator_IVQ_ROFS')


class PowerAverageOperatorA(Operator_IVQ_ROFS):
    """
        methods included as follows:
        __init__(self, data_list, weight_list, q)
    """

    def getResult(self, *waste1, **waste2):
        """
            function : 计算出 PA 算子的结果, 无权重
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : PA 集结后的数据结果，形式：（[x,y]，[x,y]）
        """
        # ta 累加结果
        ta_add = 0  # 记录 T(ai)+1 累加部分
        for i_a in range(len(self.data_list)):
            ta_add += 1 + self.get_ta(i_a)

        # 根据原始公式调用运算符号进行
        a_result = self.pow(self.data_list[0], (1 + self.get_ta(0)) / ta_add)
        for i_a in range(1, len(self.data_list)):
            a1 = a_result
            a2 = self.kmulti(self.data_list[i_a], (1 + self.get_ta(i_a)) / ta_add)
            a_result = self.add(a1, a2)

        return a_result


    def get_ta(self, i_a, *waste1, **waste2):
        """
            function : 计算 TA ，需要调用 get_sup
            i_a      : 传入模糊数 ai 的下标 int
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : T(ai) 的值
        """
        ta = 0
        # T(ai) = 累加 Sup(ai, aj)
        for j_a in range(len(self.data_list)):
            if j_a != i_a:         # 公式要求 i != j
                ta += self.get_sup(self.data_list[i_a], self.data_list[j_a])
        return ta

    def get_sup(self, a1, a2, *waste1, **waste2):
        """
            function : 求支撑度度
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : sup 的值
        """
        return 1-self.getdis(a1, a2, self.q).getDistance()

class PowerAverageOperatorGA(Operator_IVQ_ROFS):
    def getResult(self, *waste1, **waste2):
        """
            function : 计算出 PG 算子的结果, 无权重 —— 基于面向对象和基础运算发杂的写法
            return   : PA 集结后的数据结果，形式：（[x,y]，[x,y]）
        """
        # ta 累加结果
        ta_add = 0  # 记录 T(ai)+1 累加部分
        for i_a in range(len(self.data_list)):
            ta_add += 1 + self.get_ta(i_a)

        # 根据原始公式调用运算符号进行
        a_result = self.pow(self.data_list[0], (1 + self.get_ta(0)) / ta_add)
        for i_a in range(1, len(self.data_list)):
            a1 = a_result
            a2 = self.pow(self.data_list[i_a], (1 + self.get_ta(i_a)) / ta_add)
            a_result = self.multi(a1, a2)

        return a_result

    def get_ta(self, i_a, *waste1, **waste2):
        """
            function : 计算 TA ，需要调用 get_sup
            i_a      : 传入模糊数 ai 的下标 int
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : T(ai) 的值
        """
        ta = 0
        # T(ai) = 累加 Sup(ai, aj)
        for j_a in range(len(self.data_list)):
            if j_a != i_a:         # 公式要求 i != j
                ta += self.get_sup(self.data_list[i_a], self.data_list[j_a])
        return ta

    def get_sup(self, a1, a2, *waste1, **waste2):
        """
            function : 求支撑度度
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : sup 的值
        """
        return 1-self.getdis(a1, a2, self.q).getDistance()

class PowerAverageOperatorWA(Operator_IVQ_ROFS):

    def getResult(self, *waste1, **waste2):
        """
            function : 计算出 PWA 算子的结果
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : PWA 集结后的数据结果，形式：（[x,y]，[x,y]）
        """
        ta_add = 0  # 记录 T(ai)+1 累加部分
        for i_a in range(len(self.data_list)):
            ta_add += (1 + self.get_ta(i_a)) * self.weight_list[i_a]

        # 根据原始公式调用运算法则进行
        a_result = self.kmulti(self.data_list[0], ((1 + self.get_ta(0)) * self.weight_list[0]) / ta_add)
        for i_a in range(1, len(self.data_list)):
            a1 = a_result
            a2 = self.kmulti(self.data_list[i_a], ((1 + self.get_ta(i_a)) * self.weight_list[i_a]) / ta_add)
            a_result = self.add(a1, a2)

        return a_result

    def get_ta(self, i_a, *waste1, **waste2):
        """
            function : 计算 TA ，需要调用 get_sup
            i_a      : 传入模糊数 ai 的下标 int
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : T(ai) 的值
        """
        ta = 0
        # T(ai) = 累加 Sup(ai, aj)
        for j_a in range(len(self.data_list)):
            if j_a != i_a:         # 公式要求 i != j
                ta += self.weight_list[i_a]*self.get_sup(self.data_list[i_a], self.data_list[j_a])
        return ta

    def get_sup(self, a1, a2, *waste1, **waste2):
        """
            function : 求支撑度度
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : sup 的值
        """
        return 1-self.getdis(a1, a2, self.q).getDistance()

class PowerAverageOperatorWGA(Operator_IVQ_ROFS):
    def getResult(self, *waste1, **waste2):
        """
            function : 计算出 PG 算子的结果, 无权重 —— 基于面向对象和基础运算发杂的写法
            return   : PA 集结后的数据结果，形式：（[x,y]，[x,y]）
        """

        # ta 累加结果
        ta_add = 0  # 记录 T(ai)+1 累加部分
        for i_a in range(len(self.data_list)):
            ta_add += (1 + self.get_ta(i_a)) * self.weight_list[i_a]
        # 根据原始公式调用运算符号进行
        a_result = self.pow(self.data_list[0], (1 + self.get_ta(0)) * self.weight_list[0] / ta_add)
        for i_a in range(1, len(self.data_list)):
            a1 = a_result
            a2 = self.pow(self.data_list[i_a], (1 + self.get_ta(i_a)) * self.weight_list[i_a] / ta_add)
            a_result = self.multi(a1, a2)

        return a_result

    def get_ta(self, i_a, *waste1, **waste2):
        """
            function : 计算 TA ，需要调用 get_sup  —— PG 的加权 TA 和 无加权的不一样
            i_a      : 传入模糊数 ai 的下标 int
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : T(ai) 的值
        """
        ta = 0
        # T(ai) = 累加 Sup(ai, aj)
        for j_a in range(len(self.data_list)):
            if j_a != i_a:         # 公式要求 i != j
                ta += self.get_sup(self.data_list[i_a], self.data_list[j_a]) * self.weight_list[i_a]
        return ta

    def get_sup(self, a1, a2, *waste1, **waste2):
        """
            function : 求支撑度度
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : sup 的值
        """
        return 1-self.getdis(a1, a2, self.q).getDistance()

class PowerAverageOperatorOWA(Operator_IVQ_ROFS):
    # 可以用继承Operator（加上得分、排序）基本运算法则类的方式写
    def getResult(self, *waste1, **waste2):
        """
            function : 计算出 PWA 算子的结果, 无权重 —— 基于面向对象和基础运算发杂的写法
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : PWA 集结后的数据结果，形式：（[x,y]，[x,y]）
        """
        # 将 数据集备份，将类中数据集属性 替换为 排序后的数据集
        data_list = self.data_list
        self.data_list = self.sortdata()
        # 计算 TA累加 结果
        ta_add = 0  # 记录 T(ai)+1 累加部分
        for i_a in range(len(self.data_list)):
            ta_add += (1 + self.get_ta(i_a)) * self.weight_list[i_a]

        # 根据原始公式调用运算法则进行
        a_result = self.kmulti(self.data_list[0], ((1 + self.get_ta(0)) * self.weight_list[0]) / ta_add)
        for i_a in range(1, len(self.data_list)):
            a1 = a_result
            a2 = self.kmulti(self.data_list[i_a], ((1 + self.get_ta(i_a)) * self.weight_list[i_a]) / ta_add)
            a_result = self.add(a1, a2)

        # 还原数据集
        self.data_list = data_list
        return a_result

    def get_ta(self, i_a, *waste1, **waste2):
        """
            function : 计算 TA ，需要调用 get_sup
            i_a      : 传入模糊数 ai 的下标 int
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : T(ai) 的值
        """
        ta = 0
        # T(ai) = 累加 Sup(ai, aj)
        for j_a in range(len(self.data_list)):
            if j_a != i_a:         # 公式要求 i != j
                ta += self.get_sup(self.data_list[i_a], self.data_list[j_a]) ** self.weight_list[i_a]
        return ta

    def get_sup(self, a1, a2, *waste1, **waste2):
        """
            function : 求支撑度度
            a1       : 一个模糊集, 形式:（[x,y]，[x,y]）
            a2       : 一个模糊集, 形式:（[x,y]，[x,y]）
            *waste1  : 回收多余的输入参数
            **waste2 : 回收多余的输入键值对参数
            return   : sup 的值
        """
        return 1-self.getdis(a1, a2, self.q).getDistance()

if __name__ == '__main__':
    data_list=[([0.31, 0.24], [0.73, 0.72]), ([0.97, 0.12], [0.12, 0.05]),
    ([0.8, 0.52], [0.73, 0.15]), ([0.91, 0.49], [0.42, 0.47]),([0.95, 0.06], [0.19, 0.1])]
    weight_list=[0.1, 0.2, 0.3, 0.1, 0.3],
    Pa = PowerAverageOperatorOWA (data_list)
    # Pa = GA(list1)
    # Pa = WA(list1,weight_list)
    # Pa = WGA(list1,weight_list)
    # Pa = OWA(list1,weight_list)
    print(Pa.getResult())
